package com.xl.juc;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 卖票的例子 Lock锁
 *
 * synchronized与lock锁区别
 * 1、Synchronized   内置的Java关键字，  Lock 是一个Java类
 * 2、Synchronized  无法判断获取锁的状态，Lock  可以判断是否获取到了锁
 * 3、Synchronized  会自动释放锁，lock 必须要手动释放锁！如果不释放锁，死锁
 * 4、Synchronized   线程 1（获得锁，阻塞）、线程2（等待，傻傻的等）；Lock锁就不一定会等待下去
 * 5、Synchronized    可重入锁，不可以中断的，非公平；Lock ，可重入锁，可以判断锁，非公平（可以自己设置）；
 * 6、Synchronized     适合锁少量的代码同步问题，Lock  适合锁大量的同步代码！
 * @author Charley
 * @create 2020-12-27
 */
public class SaleTicket2 {
    public static void main(String[] args) {
        //并发多个线程操作同一个资源类
        Ticket2 ticket = new Ticket2();

       /* 废弃 使用Lambda表达式
       new Thread(new Runnable() {
            @Override
            public void run() {
                //业务逻辑
            }
        },"线程名称").start();*/

        new Thread(() -> {
            for (int i = 0; i < 60; i++) {
                ticket.sale();
            }
        }, "A").start();
        new Thread(() -> {
            for (int i = 0; i < 60; i++) {
                ticket.sale();
            }
        }, "B").start();
        new Thread(() -> {
            for (int i = 0; i < 60; i++) {
                ticket.sale();
            }
        }, "C").start();


    }
}

//资源类  OOP 面向对象编程 解耦
class Ticket2 {
    //属性
    private int nummber = 50;
    //默认非公平锁
    Lock lock = new ReentrantLock();

    /**
     *    public ReentrantLock() {
     sync = new NonfairSync();
     }

     /**
     * Creates an instance of {@code ReentrantLock} with the
     * given fairness policy.
     *
     * @param fair {@code true} if this lock should use a fair ordering policy
     *
     *   也可以设置公平锁
    public ReentrantLock(boolean fair) {
    sync = fair ? new ReentrantLock.FairSync() : new ReentrantLock.NonfairSync();
    }
     */
    /**
     * 公平锁：公平，排队，先后顺序  2h->2s
     *
     * 非公平锁：不公平,没有先后顺序
     */

    //卖票的方式  lock锁
    public void sale() {
        lock.lock();
        try {
            if (nummber > 0) {
                System.out.println(Thread.currentThread().getName() + "卖出了" + (nummber--) + "票，剩余" + nummber + "张票");
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();//解锁
        }
    }
}
